package com.zeyu.framework.monitors.redis.web;

import com.google.common.collect.Lists;
import com.zeyu.framework.core.web.BaseController;
import com.zeyu.framework.core.web.Result;
import com.zeyu.framework.modules.sys.utils.UserUtils;
import com.zeyu.framework.monitors.redis.RedisCollector;
import com.zeyu.framework.monitors.redis.entity.RedisStatus;
import com.zeyu.framework.monitors.redis.service.RedisService;
import com.zeyu.framework.tools.report.charts.ChartData;
import com.zeyu.framework.tools.report.dynamic.ReportUtils;
import com.zeyu.framework.utils.Collections3;
import com.zeyu.framework.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.List;

/**
 * redis 监控和操作controller
 * Created by zeyuphoenix on 16/8/27.
 */
@Controller
@RequestMapping(value = "/monitors/redis")
public class RedisController extends BaseController {

    // ================================================================
    // Constants
    // ================================================================

    // ================================================================
    // Fields
    // ================================================================

    @Autowired
    private RedisCollector redisCollector;

    @Autowired
    private RedisService redisService;

    // ================================================================
    // Constructors
    // ================================================================

    // ================================================================
    // Methods from/for super Interfaces or SuperClass
    // ================================================================

    // ================================================================
    // Public or Protected Methods
    // ================================================================

    /**
     * 页面
     */
    @RequestMapping(value = {"index", ""})
    public String index() {

        return "modules/monitors/redis";
    }

    /**
     * 获取最后一次监控的基本信息,这些信息不保存数据库
     */
    @ResponseBody
    @RequestMapping("current")
    public RedisStatus currentSatatus() {
        RedisStatus redisStatus = redisCollector.getRedisStatus();
        if (redisStatus == null) {
            // 未扫描过则扫描一次
            redisStatus = redisCollector.getCurrentRedisServerStatus();
        }
        redisStatus.setProcess(DateUtils.formatDateTimeLocal(redisStatus.getUptime() * 1000L));
        return redisStatus;
    }

    /**
     * 数据库的监控图表
     * 监控断掉的问题没办法
     */
    @ResponseBody
    @RequestMapping("chartData")
    public ChartData chartData(int type) {

        ChartData chartData = new ChartData();

        // 默认查询是5分钟一次,则1小时12个,一天288个,一个月9000以内,使用带浮动条的全部查看
        List<RedisStatus> redisStatusList = redisService.findList(new RedisStatus());
        if (!Collections3.isEmpty(redisStatusList)) {
            // 角度
            List<String> xAxis = Lists.newArrayList();
            // 指标
            List<List<Number>> series = Lists.newArrayList();

            // type --> 1:cpu  2:内存   3:内存比率  4:命令数  5:客户端连接数  6:流量

            // 转换数据
            for (RedisStatus redisStatus : redisStatusList) {
                xAxis.add(DateUtils.formatDate(redisStatus.getTime(), "dd日HH:mm"));
                if (type == 1) {
                    // cpu
                    ReportUtils.addSerie(series, 2);
                    // 'Redis服务器耗费的系统 CPU',
                    series.get(0).add(redisStatus.getUsedCpuSys());
                    // 'Redis服务器耗费的用户 CPU ',
                    series.get(1).add(redisStatus.getUsedCpuUser());

                } else if (type == 2) {
                    // 内存
                    ReportUtils.addSerie(series, 3);
                    // '由 Redis 分配器分配的内存总量，以字节（byte）为单位',
                    series.get(0).add(redisStatus.getUsedMemory());
                    // '从操作系统的角度，返回 Redis 已分配的内存总量（俗称常驻集大小）。这个值和 top 、 ps等命令的输出一致',
                    series.get(1).add(redisStatus.getUsedMemoryRss());
                    // 'Redis 的内存消耗峰值（以字节为单位）',
                    series.get(2).add(redisStatus.getUsedMemorypeak());

                } else if (type == 3) {
                    // 内存比率
                    ReportUtils.addSerie(series, 1);
                    // 'used_memory_rss 和 used_memory 之间的比率',
                    series.get(0).add(redisStatus.getMemFragmentationRatio());

                } else if (type == 4) {
                    // 命令数
                    ReportUtils.addSerie(series, 1);
                    // '服务器每秒钟执行的命令数量',
                    series.get(0).add(redisStatus.getInstantaneousOpsPerSec());

                } else if (type == 5) {
                    // 客户端连接数
                    ReportUtils.addSerie(series, 1);
                    // '已连接客户端的数量（不包括通过从属服务器连接的客户端）',
                    series.get(0).add(redisStatus.getConnectedClients());

                } else if (type == 6) {
                    // 流量
                    ReportUtils.addSerie(series, 2);
                    // '总输入字节数',
                    series.get(0).add(redisStatus.getTotalNetInputBytes());
                    // '总输出字节数',
                    series.get(1).add(redisStatus.getTotalNetOutputBytes());

                }
            }


            chartData.setxAxis(xAxis);
            chartData.setSeries(series);
        }

        return chartData;
    }

    /**
     * 数据库重新启动
     */
    @RequestMapping(value = "restart")
    @ResponseBody
    public Result restart() {
        Result result = new Result();
        if (MODE_DEMO) {
            result.setStatus(Result.ERROR);
            result.setMessage("演示模式，不允许操作!");
            return result;
        }
        if (!UserUtils.getUser().isAdmin()) {
            result.setStatus(Result.ERROR);
            result.setMessage("只能使用管理员用户才可以操作!");
            return result;
        }
        // TODO
        result.setStatus(Result.SUCCESS);
        result.setMessage("Redis数据库重新启动成功");
        return result;
    }

    // ================================================================
    // Getter & Setter
    // ================================================================

    // ================================================================
    // Private Methods
    // ================================================================

    // ================================================================
    // Inner or Anonymous Class
    // ================================================================

    // ================================================================
    // Test Methods
    // ================================================================

}
